import * as THREE from 'three';
import * as CSG from 'three-bvh-csg';
import { colors } from '../modules.js'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';

const indices = [
    0, 1, 2, 0, 2, 3,   // 前面
    4, 5, 6, 4, 6, 7,   // 后面
    0, 1, 5, 0, 5, 4,   // 底面
    3, 2, 6, 3, 6, 7,   // 顶面
    0, 3, 7, 0, 7, 4,   // 左面
    1, 2, 6, 1, 6, 5    // 右面
]

const uvs = new Float32Array([
    // 前面
    0, 1, 1, 1, 1, 0, 0, 0,  // 前面 0,6
    // 后面
    0, 1, 1, 1, 1, 0, 0, 0,  // 后面 6,6
    // 左面
    0, 0, 0, 1, 0, 0, 0, 1,  // 左面 12,6
    // 右面
    0, 1, 1, 1, 1, 0, 0, 0,  // 右面 18,6
    // 底面
    0, 1, 1, 1, 1, 0, 0, 0,  // 底面 24,6
    // 顶面
    0, 1, 1, 1, 1, 0, 0, 0,   // 顶面 30,6
]);

const indicesFW = [
    0, 1, 2, 0, 2, 3,   // 下面
    4, 5, 6, 4, 6, 7,   // 上面
    // 4, 0, 1, 4, 1, 5,
    8, 9, 10, 8, 10, 11,   // 前面
    12, 13, 14, 12, 14, 15,   // 后面
    16, 17, 18, 16, 18, 19,   // 左面
    20, 21, 22, 20, 22, 23    // 右面
]

const uvsFW = new Float32Array([
    0, 0, 1, 0, 1, 1, 0, 1,  // 下面 0,6
    0, 0, 1, 0, 1, 1, 0, 1,
    0, 0, 1, 0, 1, 1, 0, 1,  // 前面 12,6
    0, 0, 1, 0, 1, 1, 0, 1,  // 后面 18,6
    0, 0, 1, 0, 1, 1, 0, 1,  // 左面 24,6
    0, 0, 1, 0, 1, 1, 0, 1,   // 右面 30,6
]);

let scene = null;   // 场景
let camera = null;  // 相机
let renderer = null // 渲染器
let controls;    //鼠标控制器

// 创建 Raycaster 和鼠标 Vector2
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();

export const init = () => {
    // 创建场景
    scene = new THREE.Scene();
    scene.background = new THREE.Color(0x000000)

    // 创建相机
    camera = new THREE.PerspectiveCamera(90, window.innerWidth / window.innerHeight, 0.1, 1000000);
    // camera.position.x = 400;
    // camera.position.y = 100;
    // camera.position.z = 800; //14100, -77499
    camera.position.x = -141000;
    camera.position.y = -141000;
    camera.position.z = 140000;

    // 创建渲染器
    renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize(window.innerWidth, window.innerHeight);
    // 渲染器能够渲染阴影效果
    renderer.shadowMap.enabled = true;
    document.body.appendChild(renderer.domElement);

    // 添加鼠标控制
    controls = new OrbitControls(camera, renderer.domElement);
    // controls.enableDamping = true; // 使得相机移动更加平滑
    controls.dampingFactor = 0.05; // 阻尼效果

    // 创建一个平面作为底板
    const planeGeometry = new THREE.PlaneGeometry(100, 100);
    const planeMaterial = new THREE.MeshBasicMaterial({ side: THREE.DoubleSide });
    const planeMesh = new THREE.Mesh(planeGeometry, planeMaterial);
    // planeMesh.rotation.z = -0.1 * Math.PI;
    planeMesh.position.set(0, 0, 0);
    planeMesh.receiveShadow = true;
    // scene.add(planeMesh);

    // 添加网格辅助器
    const gridHelper = new THREE.GridHelper(5000, 50); // 创建一个200单位的网格，细分为50个方格
    gridHelper.rotation.x = 0.5 * Math.PI
    scene.add(gridHelper);

    // 半球光
    const hemiLight = new THREE.HemisphereLight(0xffffff, 0xffffff, 2);
    hemiLight.color.setHSL(0.6, 1, 0.6);
    hemiLight.groundColor.setHSL(0.095, 1, 0.75);
    hemiLight.position.set(0, 0, 5);
    // scene.add(hemiLight);

    // const helper = new THREE.HemisphereLightHelper( hemiLight, 5 );
    // scene.add( helper );


    // 方向光
    const directionalLight = new THREE.DirectionalLight(0xFFFFFF, 1);
    directionalLight.position.set(10, 10, 10);

    directionalLight.shadow.mapSize.width = 1024  // default
    directionalLight.shadow.mapSize.height = 1024  // default
    directionalLight.shadow.camera.near = 0.05  // default
    directionalLight.shadow.camera.far = 500  // default
    //将范围调大
    directionalLight.shadow.camera.top = 20 /// 这个是生效的属性
    directionalLight.shadow.camera.right = 20
    directionalLight.shadow.camera.left = -20
    directionalLight.shadow.camera.bottom = -20
    directionalLight.castShadow = true;
    scene.add(directionalLight);

    //方向光的辅助线
    const directionalLightHelper = new THREE.DirectionalLightHelper(
        directionalLight
    );
    // scene.add(directionalLightHelper);

    // 环境光
    const ambientLight = new THREE.AmbientLight(0xffffff, 2);
    scene.add(ambientLight);

    render();

    window.addEventListener('resize', function () {

        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();

        renderer.setSize(window.innerWidth, window.innerHeight);

    }, false);

    return {scene, controls}
}

// 渲染场景
const render = () => {
    // cube.rotation.x += 0.01;
    // cube.rotation.z += 0.01;
    controls.update(); // 更新 OrbitControls
    renderer.render(scene, camera);
    requestAnimationFrame(render); // 渲染循环
}

// 鼠标悬停
export const regHover = (cubes) => {

    const onMouseMove = (event) => {
        // 将鼠标位置归一化到 -1 到 1 之间（适用于 Three.js）
        mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
        mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

        // 通过 Raycaster 投射一条射线
        raycaster.setFromCamera(mouse, camera);

        // 检查与哪些对象相交
        const intersects = raycaster.intersectObjects(scene.children);

        cubes.forEach(cube => {
            let type = cube.userData.type
            let material = cube.material
            // 经过计算的墙体会有多个材质，取第一个
            if (cube.material instanceof Array) {
                material = cube.material[0]
            }
            try {
                material.color.set(colors[type]);  // 先将所有物体颜色重置原始色
            } catch (e) {
                console.error(cube)
            }
        });

        // 如果射线与对象相交，改变对象的颜色
        if (intersects.length > 0) {
            const element = intersects[0]
            const userData = element.object.userData
            if (userData.type) {
                let type = userData.type
                let material = element.object.material
                if (material instanceof Array) {
                    material = element.object.material[0]
                }
                material.color.set(colors[`${type}hl`]);  // 
            } else {
            }

        } else {
        }
    }

    // 监听鼠标移动事件
    window.addEventListener('mousemove', onMouseMove, false);
}

// 鼠标点击
export const regClick = () => {
    // 监听鼠标点击事件
    function onMouseClick(event) {
        // 将鼠标坐标转换为标准化设备坐标 (NDC)
        mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
        mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

        // 通过 Raycaster 检测物体
        raycaster.setFromCamera(mouse, camera);
        const intersects = raycaster.intersectObjects(scene.children);

        if (intersects.length > 0) {
            const element = intersects[0]
            const userData = element.object.userData
            console.warn(userData)
            if (userData.type) {
                // 显示提示文本并更新位置
                tooltip.style.display = 'block';
                tooltip.style.left = `${event.clientX + 10}px`;  // 将提示框移动到鼠标位置
                tooltip.style.top = `${event.clientY + 10}px`;
                let str = userData.name + '\n';
                const points = userData.points;
                points && (str += JSON.stringify(points).replace(/},/g, '},\n'));
                tooltip.textContent = str;  // 显示物体的名字
            } else {
                tooltip.style.display = 'none';
            }

        } else {
            tooltip.style.display = 'none';
        }
    }

    // 监听鼠标点击事件
    window.addEventListener('click', onMouseClick, false);
}

//画长方体
export const drawCubeByPlane = (pointObj) => {
    if (typeof pointObj != 'object') {
        throw new Error(`需要参数类型为object,传入的参数类型为${typeof pointObj}`)
    }
    if (!pointObj.hasOwnProperty('type')) {
        throw new Error(`参数须包含type字段`)
    }

    const type = pointObj.type
    const points = pointObj.points
    var vertices = pointsToVertices(points, type)

    var geometry = new THREE.BufferGeometry();
    geometry.setAttribute("position", new THREE.BufferAttribute(vertices, 3));
    if (indices != null && typeof (indices) != 'undefined') {
        geometry.setIndex(indices);
    }
    geometry.setAttribute('uv', new THREE.BufferAttribute(uvs, 2))

    var color = colors[type]

    geometry.computeVertexNormals(); // 计算法线，确保光照正常
    var material = new THREE.MeshStandardMaterial({
        color: color,
        side: THREE.DoubleSide,
        // wireframe: true  //是否以线框模式渲染物体
        opacity: 0.5,   //透明度 0-1
        transparent: false   //指示材质是否透明。如果设置为true，则材质将考虑透明度（opacity）的影响。
    });

    var cube = new CSG.Brush(geometry, material);
    let result = cube
    if (pointObj.door || pointObj.window) {  // 有门窗
        const evaluator = new CSG.Evaluator();

        const doorPoint = pointObj.door
        const windowPoint = pointObj.window
        if (doorPoint) {
            let doorvts = pointsToVertices(doorPoint, "M")
            let doorGeometry = new THREE.BufferGeometry();
            doorGeometry.setAttribute("position", new THREE.BufferAttribute(doorvts, 3));
            doorGeometry.setIndex(indices);
            doorGeometry.setAttribute('uv', new THREE.BufferAttribute(uvs, 2))
            doorGeometry.computeVertexNormals()
            let doorMaterial = new THREE.MeshStandardMaterial({
                color: 0x00000000,
                side: THREE.DoubleSide,
            });
            let doorMesh = new CSG.Brush(doorGeometry, doorMaterial);
            result = evaluator.evaluate(result, doorMesh, CSG.SUBTRACTION)
        }

        if (windowPoint) {
            let windowvts = pointsToVertices(windowPoint, "C")
            let windowGeometry = new THREE.BufferGeometry();
            windowGeometry.setAttribute("position", new THREE.BufferAttribute(windowvts, 3));
            windowGeometry.setIndex(indices);
            windowGeometry.setAttribute('uv', new THREE.BufferAttribute(uvs, 2))
            windowGeometry.computeVertexNormals()
            let wndowMaterial = new THREE.MeshStandardMaterial({
                color: 0x00000000,
                side: THREE.DoubleSide,
            });
            let windowMesh = new CSG.Brush(windowGeometry, wndowMaterial);
            result = evaluator.evaluate(result, windowMesh, CSG.SUBTRACTION)
        }

    }

    if (pointObj.formworks) {
        drawFormworks(pointObj)
    }

    result && (result.castShadow = true);
    result && (result.userData = { ...pointObj });
    scene.add(result);
    return result;
}

function drawFormworks(obj) {
    console.warn(obj)
    const points = obj.points
    let direction = 'hor'
    let disX = points[3].x - points[0].x
    let disY = points[3].x - points[0].x
    let distance = disX
    if (disY > disX) {
        direction = 'ver'
        distance = disY
    }

}

//长方体给定底部4个顶点计算8个点顶点的坐标
function pointsToVertices(points, type) {
    //判别点的合法性
    if (points == null || typeof (points) == 'undefined') {
        return null
    }
    var iSize = 0
    if (points instanceof Array) {
        iSize = points.length
    }
    if (iSize < 4 || iSize > 4) {
        return null
    }

    // console.log('iSize=', iSize, ' type=', type)
    var vertices = new Float32Array(24)
    var idx = 0
    var i
    var point
    var x
    var y
    var z
    var z1
    for (i = 0; i < iSize; i++) {
        point = points[i]

        // console.log('point=', point)
        if (point == null || typeof (point) == 'undefined') {
            continue
        }
        x = point.x
        y = point.y
        z = point.z

        // console.log('XXX i=', i, ' x=', x, 'y=', y, 'z=', z)

        if ((x == null || typeof (x) == 'undefined') || (y == null || typeof (y) == 'undefined')) {
            continue
        }
        if ((z == null || typeof (z) == 'undefined')) {
            z = 0
        }
        z1 = z
        if (type == 'Z') {
            z1 = z + 330 + 60
            z = z + 0
        } else if (type == 'L') {
            z1 = z + 330 + 60
            z = z + 330
        } else if (type == 'LQ') {
            z1 = z + 330 + 60
            z = z + 0
        } else if (type == 'M') {
            z1 = z + 180
            z = z + 0
        } else if (type == 'C') {
            z1 = z + 250
            z = z + 100
        }

        // console.log('x=', x, ' y=', y, ' z=', z, ' z1=', z1)
        vertices[idx++] = x
        vertices[idx + 11] = x
        vertices[idx++] = y
        vertices[idx + 11] = y
        vertices[idx++] = z
        vertices[idx + 11] = z1
    }
    return vertices
}



export default {
    init, drawCubeByPlane, regHover, regClick, controls
}